package com.spelet;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;

import com.spelet.screens.Game;
import com.spelet.screens.LevelSelect;
import com.spelet.screens.CustomGame;
import com.spelet.screens.MainMenu;
import com.spelet.screens.MapEditor;
import com.spelet.simulation.Bee;
import com.spelet.simulation.Map;
import com.spelet.simulation.Simulation;

public class Renderer {
	public SpriteBatch sb;
	public SpriteBatch sb2;
	public OrthographicCamera mapCam, mapUICam;
	private static Renderer singleton;
	public Rectangle camRect;
	public Rectangle spriteRect;
	public boolean camLerping;
	private String rks,bks,yks;
	private int rk,bk,yk;

	public static Renderer getInstance()
	{
		if(singleton==null)
			singleton = new Renderer();
		return singleton;
	}


	private Renderer() {
		sb = new SpriteBatch();
		sb2 = new SpriteBatch();
		camRect = new Rectangle(0,0,0,0);
		spriteRect = new Rectangle(0,0,0,0);
		rk = 0; bk = 0; yk = 0;
		rks = "x 0"; bks = "x 0"; yks = "x 0";
		mapCam = new OrthographicCamera();
		mapCam.zoom = 1f;
		mapCam.position.set(Gdx.graphics.getWidth()*mapCam.zoom/2,Gdx.graphics.getHeight()*mapCam.zoom/2,0);
		mapUICam = new OrthographicCamera();
		mapUICam.zoom = 1f;
		mapUICam.position.set(Gdx.graphics.getWidth()*mapUICam.zoom/2,Gdx.graphics.getHeight()*mapUICam.zoom/2,0);
		mapUICam.viewportHeight = Gdx.graphics.getHeight();
		mapUICam.viewportWidth = Gdx.graphics.getWidth();
		mapUICam.update();
	}

	public void renderGame(Game game, Simulation sim) {

		sim.gameCam.viewportHeight = Gdx.graphics.getHeight();
		sim.gameCam.viewportWidth = Gdx.graphics.getWidth();
		if (camLerping) {
			sim.gameCam.position.lerp(new Vector3(sim.character.spriteX,sim.character.spriteY,0), 0.05f);
			spriteRect.set(sim.character.spriteX,sim.character.spriteY,64,64);
			if (sim.gameCam.position.x < Gdx.graphics.getWidth()*sim.gameCam.zoom/2) {
				sim.gameCam.position.x = Gdx.graphics.getWidth()*sim.gameCam.zoom/2;
			}
			if (sim.gameCam.position.y < Gdx.graphics.getHeight()*sim.gameCam.zoom/2) {
				sim.gameCam.position.y = Gdx.graphics.getHeight()*sim.gameCam.zoom/2;
			}
			if (sim.gameCam.position.x > sim.map.cols*64-Gdx.graphics.getWidth()*sim.gameCam.zoom/2) {
				sim.gameCam.position.x = sim.map.cols*64-Gdx.graphics.getWidth()*sim.gameCam.zoom/2;
			}
			if (sim.gameCam.position.y > sim.map.rows*64-Gdx.graphics.getHeight()*sim.gameCam.zoom/2) {
				sim.gameCam.position.y = sim.map.rows*64-Gdx.graphics.getHeight()*sim.gameCam.zoom/2;
			}
			if (spriteRect.contains(sim.gameCam.position.x, sim.gameCam.position.y)) {
				camLerping = false;
			}
		}

		sim.gameCam.update();
		camRect.set(sim.gameCam.position.x-sim.gameCam.viewportWidth/2*sim.gameCam.zoom,sim.gameCam.position.y-sim.gameCam.viewportHeight/2*sim.gameCam.zoom,(sim.gameCam.viewportWidth)*sim.gameCam.zoom,(sim.gameCam.viewportHeight)*sim.gameCam.zoom);

		sb.setProjectionMatrix(sim.gameCam.combined);
		float ambientR = 0.5f;
		float ambientB = 0.5f;
		float ambientG = 0.5f;
		float ambientA = 1f;
		sb.begin();
		int charAfter = sim.character.spriteY/64;
		for (int y = sim.map.terrainBlocks[0].length-1; y >= 0; y--) {
			for (int x = 0; x < sim.map.terrainBlocks.length; x++) {
				spriteRect.set(sim.map.terrainBlocks[x][y].spriteX,sim.map.terrainBlocks[x][y].spriteY,64,64);
				if (camRect.overlaps(spriteRect)) {
					sim.map.terrainBlocks[x][y].render(sb, ambientR, ambientB, ambientG, ambientA);
				}
			}
		}
		for (int y = sim.map.terrainBlocks[0].length-1; y >= 0; y--) {
			for (int x = 0; x < sim.map.terrainBlocks.length; x++) {
				spriteRect.set(sim.map.terrainBlocks[x][y].fxPos,sim.map.terrainBlocks[x][y].fyPos,36,36);
				if (camRect.overlaps(spriteRect)) {
					sim.map.terrainBlocks[x][y].renderFlow(sb, ambientR, ambientB, ambientG, ambientA);
				}
			}
			for (int i = 0; i < sim.map.renderAtRows.get(y).size; i++) {
				spriteRect.set(sim.map.renderAtRows.get(y).get(i).tileX*64,sim.map.renderAtRows.get(y).get(i).tileY*64,64,64);
				if (camRect.overlaps(spriteRect)) {
					sim.map.renderAtRows.get(y).get(i).render(sb, ambientR, ambientB, ambientG, ambientA);
				}
			}
			sim.theBee.renderhive(sb,ambientR,ambientB,ambientG,ambientA);


			if (y == sim.theBee.currentlyAtRow) {
				spriteRect.set(sim.theBee.spriteX,sim.theBee.spriteY,64,64);
				if (camRect.overlaps(spriteRect)) 
					sim.theBee.render(sb,ambientR,ambientB,ambientG,ambientA);
			}

			for(int i = 0; i < sim.zerglings.size; i++){
				Bee zerg = sim.zerglings.get(i);
				if (y == zerg.currentlyAtRow) {			
					spriteRect.set(zerg.spriteX,zerg.spriteY,64,64);
					if (camRect.overlaps(spriteRect)) 
						zerg.render(sb,ambientR,ambientB,ambientG,ambientA);
				}
			}

			if (y == charAfter) {
				spriteRect.set(sim.character.spriteX,sim.character.spriteY,64,128);
				if (camRect.overlaps(spriteRect)) 
					sim.character.render(sb,ambientR,ambientB,ambientG,ambientA);
			}
		}
		sb.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE);
		for (int y = sim.map.terrainBlocks[0].length-1; y >= 0; y--) {
			for (int i = 0; i < sim.map.renderAtRows.get(y).size; i++) {
				spriteRect.set(sim.map.renderAtRows.get(y).get(i).tileX*64,sim.map.renderAtRows.get(y).get(i).tileY*64,64,64);
				if (camRect.overlaps(spriteRect)) {
					sim.map.renderAtRows.get(y).get(i).renderLights(sb);
				}
			}
		}
		sb.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
		for (int y = sim.map.terrainBlocks[0].length-1; y >= 0; y--) {
			for (int i = 0; i < sim.map.renderAtRows.get(y).size; i++) {
				spriteRect.set(sim.map.renderAtRows.get(y).get(i).tileX*64,sim.map.renderAtRows.get(y).get(i).tileY*64,64,64);
				if (camRect.overlaps(spriteRect)) {
					sim.map.renderAtRows.get(y).get(i).renderLamps(sb);
				}
			}
		}
		sim.gameUICam.viewportHeight = Gdx.graphics.getHeight();
		sim.gameUICam.viewportWidth = Gdx.graphics.getWidth();
		sim.gameUICam.update();
		sb.setProjectionMatrix(sim.gameUICam.combined);

		StaticSprites.exit.setBounds(Gdx.graphics.getWidth()-StaticVariables.buttonSize*1.15f,StaticVariables.buttonSize*0.15f,
				StaticVariables.buttonSize,StaticVariables.buttonSize);
		StaticSprites.exit.draw(sb);

		float originalWidth = StaticSprites.redkey[0].getWidth();
		float originalHeight = StaticSprites.redkey[0].getHeight();

		float uiKeySize = StaticVariables.buttonSize*0.75f;
		float startVal = Gdx.graphics.getWidth()*0.02f;
		float butOffset = StaticVariables.buttonSize*0.925f;

		float txtFromKey = StaticVariables.buttonSize*0.55f;

		StaticSprites.redkey[0].setPosition(startVal, StaticVariables.buttonSize*0.15f);
		StaticSprites.redkey[0].setSize(uiKeySize, uiKeySize);
		StaticSprites.redkey[0].draw(sb);
		if(sim.character.redKeys != rk) {
			rk = sim.character.redKeys;
			rks = "x "+Integer.toString(rk);
		}
		StaticFonts.basicFont.draw(sb, rks, startVal+txtFromKey, StaticVariables.buttonSize*0.55f);

		StaticSprites.bluekey[0].setPosition(startVal+butOffset, StaticVariables.buttonSize*0.15f);
		StaticSprites.bluekey[0].setSize(uiKeySize, uiKeySize);
		StaticSprites.bluekey[0].draw(sb);
		if(sim.character.blueKeys != bk) {
			bk = sim.character.blueKeys;
			bks = "x "+Integer.toString(bk);
		}
		StaticFonts.basicFont.draw(sb, bks, startVal+butOffset+txtFromKey, StaticVariables.buttonSize*0.55f);

		StaticSprites.yellowkey[0].setPosition(startVal+butOffset*2f, StaticVariables.buttonSize*0.15f);
		StaticSprites.yellowkey[0].setSize(uiKeySize, uiKeySize);
		StaticSprites.yellowkey[0].draw(sb);
		if(sim.character.yellowKeys != yk) {
			yk = sim.character.yellowKeys;
			yks = "x "+Integer.toString(yk);
		}
		StaticFonts.basicFont.draw(sb, yks, startVal+butOffset*2f+txtFromKey, StaticVariables.buttonSize*0.55f);

		StaticSprites.redkey[0].setSize(originalWidth, originalHeight);
		StaticSprites.bluekey[0].setSize(originalWidth, originalHeight);
		StaticSprites.yellowkey[0].setSize(originalWidth, originalHeight);
		if (!game.testing && !game.custom && game.level > 0) {
			if (game.timer < 500) {
				StaticSprites.levelNames[game.level-1].setPosition(Gdx.graphics.getWidth()*sim.gameCam.zoom/2-StaticSprites.levelNames[game.level-1].getWidth()/2, Gdx.graphics.getHeight()*sim.gameCam.zoom/2);
				StaticSprites.levelNames[game.level-1].draw(sb,(game.timer-500)/500);
			} else if (game.timer < 1500) {
				StaticSprites.levelNames[game.level-1].setPosition(Gdx.graphics.getWidth()*sim.gameCam.zoom/2-StaticSprites.levelNames[game.level-1].getWidth()/2, Gdx.graphics.getHeight()*sim.gameCam.zoom/2);
				StaticSprites.levelNames[game.level-1].draw(sb);
			} else if (game.timer < 2000) {
				StaticSprites.levelNames[game.level-1].setPosition(Gdx.graphics.getWidth()*sim.gameCam.zoom/2-StaticSprites.levelNames[game.level-1].getWidth()/2, Gdx.graphics.getHeight()*sim.gameCam.zoom/2);
				StaticSprites.levelNames[game.level-1].draw(sb,1-(game.timer-1500)/500);
			}
		}
		sb.end();
	}

	public void renderLoadFile(CustomGame lf) {
		sb.begin();
		lf.render(sb);
		sb.end();
	}
	public void renderMapEditor(MapEditor me, Map map, com.spelet.simulation.Character bob) {		
		float w = StaticVariables.percentWidth;
		//float h = StaticVariables.percentHeight;

		mapCam.viewportHeight = Gdx.graphics.getHeight();
		mapCam.viewportWidth = Gdx.graphics.getWidth();

		mapCam.update();
		sb.setProjectionMatrix(mapCam.combined);

		sb.begin();

		int charAfter = bob.spriteY/64;
		for (int x = 0; x < map.terrainBlocks.length; x++) {
			if (me.draggedToColnr == x) {
				StaticSprites.dragDownS.setPosition(x*64, map.terrainBlocks[0].length*64);
				StaticSprites.dragDownS.draw(sb);
			} else {
				StaticSprites.dragDown.setPosition(x*64, map.terrainBlocks[0].length*64);
				StaticSprites.dragDown.draw(sb);
			}
		}
		StaticSprites.addRow.setPosition(map.terrainBlocks.length*64,map.terrainBlocks[0].length*64);
		StaticSprites.addRow.draw(sb);
		StaticSprites.addRow.setPosition(-64,-64);
		StaticSprites.addRow.draw(sb);
		StaticSprites.removeRow.setPosition(map.terrainBlocks.length*64,map.terrainBlocks[0].length*64+64);
		StaticSprites.removeRow.draw(sb);
		StaticSprites.removeRow.setPosition(-128,-64);
		StaticSprites.removeRow.draw(sb);
		for (int y = 0; y < map.terrainBlocks[0].length;y++) {
			if (me.draggedToRownr == y) {
				StaticSprites.dragRightS.setPosition(-64, y*64);
				StaticSprites.dragRightS.draw(sb);
			} else {
				StaticSprites.dragRight.setPosition(-64, y*64);
				StaticSprites.dragRight.draw(sb);
			}
		}
		if (me.renderingTerrain) {
			for (int y = map.terrainBlocks[0].length-1; y >= 0; y--) {
				for (int x = 0; x < map.terrainBlocks.length; x++) {
					map.terrainBlocks[x][y].render(sb,1,1,1,1);
				}
			}
		}

		if (me.renderingBlocks || me.renderingTerrain) { 
			for (int y = map.terrainBlocks[0].length-1; y >= 0; y--) {
				if (me.renderingBlocks) { 
					for (int i = 0; i < map.renderAtRows.get(y).size; i++) {
						map.renderAtRows.get(y).get(i).render(sb,1,1,1,1);
					}
				}
				if(y==charAfter)
					bob.render(sb,1,1,1,1);
			}
		}
		
		sb.setProjectionMatrix(mapUICam.combined);
		me.viewbar.render(sb);
		sb.draw(StaticTextures.mapbottom, 0, 0, w*100f, StaticVariables.barSize);
		StaticSprites.terrain.setBounds(StaticVariables.edgeDistance, StaticVariables.edgeDistance, 
				StaticVariables.buttonSize, StaticVariables.buttonSize);
		StaticSprites.terrain.draw(sb);
		StaticSprites.objects.setBounds(StaticVariables.edgeDistance+StaticVariables.buttonOffset*1f,
				StaticVariables.edgeDistance, StaticVariables.buttonSize, StaticVariables.buttonSize);
		StaticSprites.objects.draw(sb);
		StaticSprites.test.setBounds(StaticVariables.edgeDistance+StaticVariables.buttonOffset*2f,
				StaticVariables.edgeDistance, StaticVariables.buttonSize, StaticVariables.buttonSize);
		StaticSprites.test.draw(sb);
		StaticSprites.resize.setBounds(StaticVariables.edgeDistance+StaticVariables.buttonOffset*3f, 
				StaticVariables.edgeDistance, StaticVariables.buttonSize, StaticVariables.buttonSize);
		StaticSprites.resize.draw(sb);
		StaticSprites.save.setBounds(StaticVariables.edgeDistance+StaticVariables.buttonOffset*4f, 
				StaticVariables.edgeDistance, StaticVariables.buttonSize, StaticVariables.buttonSize);
		StaticSprites.save.draw(sb);
		StaticSprites.load.setBounds(StaticVariables.edgeDistance+StaticVariables.buttonOffset*5f, 
				StaticVariables.edgeDistance, StaticVariables.buttonSize, StaticVariables.buttonSize);
		StaticSprites.load.draw(sb);
		StaticSprites.exit.setBounds(StaticVariables.edgeDistance+StaticVariables.buttonOffset*6f, 
				StaticVariables.edgeDistance, StaticVariables.buttonSize, StaticVariables.buttonSize);
		StaticSprites.exit.draw(sb);
		sb.flush();
		if (me.chooseTerrainBrush)
			me.ctb.render(mapUICam,sb);
		else if (me.chooseBlockBrush)
			me.cbb.render(mapUICam, sb);
		else if (me.loadingFile) {
			me.lmf.render(mapUICam,sb);
		} else if (me.savingFile) {
			me.smf.render(mapUICam,sb);
		} else if (me.chooseNewSize) {
			me.rm.render(mapUICam, sb);
		}
		sb.end();
	}
	public void renderLevelSelect(LevelSelect ls) {
		ls.cam.zoom = (float)64f*10f/(float)Gdx.graphics.getWidth();
		ls.cam.position.set(Gdx.graphics.getWidth()*ls.cam.zoom/2,Gdx.graphics.getHeight()*ls.cam.zoom/2,0);
		ls.cam.viewportHeight = Gdx.graphics.getHeight();
		ls.cam.viewportWidth = Gdx.graphics.getWidth();
		ls.cam.update();
		sb.setProjectionMatrix(ls.cam.combined);
		sb.begin();
		ls.bg.draw(sb);
		ls.renderLevels(sb);
		sb.end();
	}
	public void renderMainMenu(MainMenu mm) {
		mm.cam.zoom = 800f/(float)Gdx.graphics.getHeight();
		mm.cam.position.set(Gdx.graphics.getWidth()*mm.cam.zoom/2,Gdx.graphics.getHeight()*mm.cam.zoom/2,0);
		mm.cam.viewportHeight = Gdx.graphics.getHeight();
		mm.cam.viewportWidth = Gdx.graphics.getWidth();
		mm.cam.update();
		sb.setProjectionMatrix(mm.cam.combined);
		sb.begin();
		mm.renderMainMenu(sb);
		sb.end();
	}
}